class Bubbles2 extends egret.DisplayObjectContainer {
    private balls: Array<Ball>
    private numBalls: number = 10
    private centerBall: Ball
    private bouncing: number = -1
    private springging: number = 0.01
    private gravity: number = 0.10

    public constructor() {
        super()
        this.once(egret.Event.ADDED_TO_STAGE, this.onAddToStage, this)
    }

    private onAddToStage(): void {
        this.balls = new Array<Ball>()
        this.centerBall = new Ball(50, 0xCCCCCC)
        this.addChild(this.centerBall)
        this.centerBall.x = this.stage.stageWidth / 2
        this.centerBall.y = this.stage.stageHeight / 2
        this.centerBall.static = true

        for (let i = 0; i < this.numBalls; ++i) {
            let ball:Ball = new Ball(Math.random() * 40 + 5, Math.random() * 0xFFFFFF)
            ball.x = Math.random() * this.stage.stageWidth
            ball.y = Math.random() * this.stage.stageHeight
            ball.vx = Math.random() * 6 - 3
            ball.vy = Math.random() * 6 - 3
            this.addChild(ball)
            this.balls.push(ball)
        }

        this.addEventListener(egret.Event.ENTER_FRAME, this.onEnterFrame, this)
    }

    private onEnterFrame() {
        for (let i = 0; i < this.numBalls - 1; ++i) {
            let ball0 = this.balls[i]
            for (let j = i+1; j < this.numBalls; ++j) {
                let ball1 = this.balls[j]
                this.hit(ball0, ball1)
            }
        }

        for (let i = 0; i < this.numBalls; ++i) {
            let ball = this.balls[i]
            this.hit(this.centerBall, ball)
            this.move(ball)
        }
    }

    
    private hit(a:Ball, b: Ball) {
        let { isHit, angle } = this.hitTestBall(a, b)
        if (isHit) {
            let minDist = b.radius + a.radius
            let tx = a.x + Math.cos(angle) * minDist
            let ty = a.y + Math.sin(angle) * minDist
            let ax = (tx - b.x) * this.springging
            let ay = (ty - b.y) * this.springging
            if (!a.static) { // a 不是静态球体
                a.vx -= ax
                a.vy -= ay
            }
            b.vx += ax
            b.vy += ay
        }
    }

    private move(ball: Ball) {
        ball.vy += this.gravity
        ball.x += ball.vx
        ball.y += ball.vy
        this.bounce(ball)
    }

    private bounce(ball: Ball) {
        if (ball.x + ball.radius > this.stage.stageWidth) {
            ball.x = this.stage.stageWidth - ball.radius
            ball.vx *= this.bouncing
        } else if (ball.x - ball.radius < 0) {
            ball.x = ball.radius
            ball.vx *= this.bouncing
        }

        if (ball.y + ball.radius > this.stage.stageHeight) {
            ball.y = this.stage.stageHeight - ball.radius
            ball.vy *= this.bouncing
        } else if (ball.y - ball.radius < 0) {
            ball.y = ball.radius
            ball.vy *= this.bouncing
        }
    }

    /**
     *  a 是基准被减的球 
     */
    private hitTestBall(a: Ball, b: Ball): { isHit: boolean, angle: number } {
        let dx = b.x - a.x
        let dy = b.y - a.y
        let point = egret.Point.create(dx, dy)
        let isHit: boolean = false
        if (point.length < a.radius + b.radius) {
            isHit = true
        }
        egret.Point.release(point)
        return { isHit, angle: Math.atan2(dy, dx) }
    }
}